home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / zutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-15  |  24.1 KB  |  1,061 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.    
  4. */
  5.  
  6. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  7.  
  8. #ifndef lint
  9. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ir/RCS/zutil.c,v 1.5 1994/08/16 11:48:08 pfeifer Exp $";
  10. #endif
  11.  
  12. /* Change log:
  13.  * $Log: zutil.c,v $
  14.  * Revision 1.5  1994/08/16  11:48:08  pfeifer
  15.  * adden register definition in readCompressedInteger, purify keeps
  16.  * unhappy :(
  17.  *
  18.  * Revision 1.4  1994/08/12  17:42:59  pfeifer
  19.  * Speeded up, but purify still complains:
  20.  * ****  Purify'd ./waisserver  (pid 8145, forked from ./waisserver pid 8140)  ****
  21.  * Purify (umr): uninitialized memory read:
  22.  *   * This is occurring while in:
  23.  *     readCompressedInteger [line 241, zutil.c, pc=0xb9384]
  24.  *     readTag      [line 319, zutil.c, pc=0xb97a8]
  25.  *     readAny      [line 432, zutil.c, pc=0xb9e14]
  26.  *     readString   [line 533, zutil.c, pc=0xba44c]
  27.  *     readInitInfo [line 118, wprot.c, pc=0x776fc]
  28.  *     readInitAPDU [line 234, zprot.c, pc=0x8c69c]
  29.  *   * Reading 1 byte from 0xeffe5bb7 on the stack
  30.  *     This is local variable "byte" in function readCompressedInteger.
  31.  *
  32.  * ****  Purify'd ./waisserver  (pid 8145, forked from ./waisserver pid 8140)  ****
  33.  * Purify (umr): uninitialized memory read:
  34.  *   * This is occurring while in:
  35.  *     readCompressedInteger [line 242, zutil.c, pc=0xb93b4]
  36.  *     readTag      [line 319, zutil.c, pc=0xb97a8]
  37.  *     readAny      [line 432, zutil.c, pc=0xb9e14]
  38.  *     readString   [line 533, zutil.c, pc=0xba44c]
  39.  *     readInitInfo [line 118, wprot.c, pc=0x776fc]
  40.  *     readInitAPDU [line 234, zprot.c, pc=0x8c69c]
  41.  *   * Reading 1 byte from 0xeffe5bb7 on the stack
  42.  *     This is local variable "byte" in function readCompressedInteger.
  43.  *
  44.  * ****  Purify'd ./waisserver  (pid 8145, forked from ./waisserver pid 8140)  ****
  45.  * Purify (umr): uninitialized memory read:
  46.  *   * This is occurring while in:
  47.  *     readCompressedInteger [line 241, zutil.c, pc=0xb9384]
  48.  *     readAny      [line 433, zutil.c, pc=0xb9e38]
  49.  *     readString   [line 533, zutil.c, pc=0xba44c]
  50.  *     readInitInfo [line 118, wprot.c, pc=0x776fc]
  51.  *     readInitAPDU [line 234, zprot.c, pc=0x8c69c]
  52.  *     handleInit   [line 359, ir.c, pc=0x19d60]
  53.  *   * Reading 1 byte from 0xeffe5c27 on the stack
  54.  *     This is local variable "byte" in function readCompressedInteger.
  55.  *
  56.  * ****  Purify'd ./waisserver  (pid 8145, forked from ./waisserver pid 8140)  ****
  57.  * Purify (umr): uninitialized memory read:
  58.  *   * This is occurring while in:
  59.  *     readCompressedInteger [line 242, zutil.c, pc=0xb93b4]
  60.  *     readAny      [line 433, zutil.c, pc=0xb9e38]
  61.  *     readString   [line 533, zutil.c, pc=0xba44c]
  62.  *     readInitInfo [line 118, wprot.c, pc=0x776fc]
  63.  *     readInitAPDU [line 234, zprot.c, pc=0x8c69c]
  64.  *     handleInit   [line 359, ir.c, pc=0x19d60]
  65.  *   * Reading 1 byte from 0xeffe5c27 on the stack
  66.  *     This is local variable "byte" in function readCompressedInteger.
  67.  *
  68.  * Revision 1.3  1994/05/20  12:58:28  pfeifer
  69.  * beta
  70.  *
  71.  * Revision 1.2  1994/03/08  21:07:27  pfeifer
  72.  * Patchlevel 04
  73.  *
  74.  * Revision 1.1  1993/02/16  15:05:35  freewais
  75.  * Initial revision
  76.  *
  77.  * Revision 1.6  92/03/26  18:27:16  jonathan
  78.  * Fixed function declaration.
  79.  * 
  80.  * Revision 1.5  92/03/07  19:41:14  jonathan
  81.  * ANSIfied argument list.
  82.  * 
  83.  * Revision 1.4  92/02/12  14:01:37  jonathan
  84.  * Added "$Log" so RCS will put the log message in the header
  85.  * 
  86.  *
  87.    3.26.90    Harry Morris, morris@think.com
  88.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  89.    4.11.90  HWM - fixed include file names, changed 
  90.                    - writeCompressedIntegerWithPadding() to
  91.                   writeCompressedIntWithPadding()
  92.                 - generalized conditional includes (see c-dialect.h)
  93.    3.7.91   Jonny Goldman.  Replaced "short" in makeBitMap with "int" line 632.
  94. */
  95.  
  96. #define _C_utils_Z39_50_
  97.  
  98. #include "zutil.h"
  99.  
  100. #include <math.h>
  101. #include "cdialect.h"
  102. /* #include <string.h> */
  103.  
  104. char* readErrorPosition = NULL; /* pos where buf stoped making sense */
  105.  
  106. /*----------------------------------------------------------------------*/
  107. /* A note on error handling 
  108.    read - these are low level routines, they do not check the type tags
  109.    which (sometimes) preceed the data (this is done by the higher
  110.    level functions which call these functions).  There is no 
  111.    attempt made to check that the reading does not exceed the read
  112.    buffer.  Such cases should be very rare and usually will be 
  113.    caught by the calling functions. (note - it is unlikely that 
  114.    a series of low level reads will go far off the edge without
  115.    triggering a type error.  However, it is possible for a single
  116.    bad read in an array function (eg. readAny) to attempt to read a 
  117.    large ammount, possibly causing a segmentation violation or out
  118.    of memory condition.
  119.  */
  120. /*----------------------------------------------------------------------*/
  121.  
  122. diagnosticRecord* 
  123. makeDiag(surrogate,code,addInfo)
  124. boolean surrogate;
  125. char* code;
  126. char* addInfo;
  127. {
  128.   diagnosticRecord* diag = 
  129.     (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  130.   
  131.   diag->SURROGATE = surrogate;
  132.   memcpy(diag->DIAG,code,DIAGNOSTIC_CODE_SIZE);
  133.   diag->ADDINFO = s_strdup(addInfo); 
  134.  
  135.   return(diag);
  136. }
  137.  
  138. /*----------------------------------------------------------------------*/
  139.  
  140. void 
  141. freeDiag(diag)
  142. diagnosticRecord* diag;
  143.   if (diag != NULL)
  144.     { if (diag->ADDINFO != NULL)
  145.     s_free(diag->ADDINFO);
  146.     s_free(diag);
  147.       }
  148. }
  149.  
  150. /*----------------------------------------------------------------------*/
  151.  
  152. #define END_OF_RECORD    0x1D
  153.  
  154. char* 
  155. writeDiag(diag,buffer,len)
  156. diagnosticRecord* diag;
  157. char* buffer;
  158. long* len;
  159. /* diagnostics (as per Appendix D) have a very weird format - this changes
  160.    in SR-1
  161.  */
  162. {
  163.   char* buf = buffer;
  164.   long  length;
  165.   
  166.   if (diag == NULL)        /* handle unspecified optional args */
  167.     return(buf);
  168.  
  169.   buf = writeTag(DT_DatabaseDiagnosticRecords,buf,len);
  170.   CHECK_FOR_SPACE_LEFT(0L,len);
  171.   
  172.   length = 3; 
  173.   if (diag->ADDINFO != NULL)
  174.     length += strlen(diag->ADDINFO);
  175.     
  176.   if (length >= 0xFFFF )    /* make sure the length is reasonable */
  177.     { length = 0xFFFF - 1;
  178.       diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
  179.     }
  180.    
  181.   buf = writeBinaryInteger(length,2L,buf,len);
  182.  
  183.   CHECK_FOR_SPACE_LEFT(1L,len);
  184.   buf[0] = diag->DIAG[0]; 
  185.   buf++;
  186.   
  187.   CHECK_FOR_SPACE_LEFT(1L,len);
  188.   buf[0] = diag->DIAG[1];
  189.   buf++;
  190.   
  191.   if (length > 3)
  192.     { CHECK_FOR_SPACE_LEFT(3L,len);
  193.       memcpy(buf,diag->ADDINFO,(size_t)length - 3);
  194.       buf += length - 3;
  195.     }
  196.    
  197.   CHECK_FOR_SPACE_LEFT(1L,len);
  198.   buf[0] = diag->SURROGATE;
  199.   buf++;
  200.   
  201.   CHECK_FOR_SPACE_LEFT(1L,len);
  202.   buf[0] = END_OF_RECORD;
  203.   buf++;
  204.  
  205.   return(buf);
  206. }
  207.  
  208. /*----------------------------------------------------------------------*/
  209.  
  210. char* 
  211. readDiag(diag,buffer)
  212. diagnosticRecord** diag;
  213. char* buffer;
  214. {
  215.   char* buf = buffer;
  216.   diagnosticRecord* d 
  217.     = (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  218.   data_tag tag;
  219.   long len;
  220.   
  221.   buf = readTag(&tag,buf);
  222.   
  223.   buf = readBinaryInteger(&len,2L,buf);
  224.   
  225.   d->DIAG[0] = buf[0];
  226.   d->DIAG[1] = buf[1];
  227.   d->DIAG[2] = '\0';
  228.     
  229.   if (len > 3)
  230.     { d->ADDINFO = (char*)s_malloc((size_t)(len - 3 + 1));
  231.       memcpy(d->ADDINFO,(char*)(buf + 2),(size_t)(len - 3));
  232.       d->ADDINFO[len - 3] = '\0';
  233.     }
  234.   else
  235.     d->ADDINFO = NULL;
  236.     
  237.   d->SURROGATE = buf[len - 1];
  238.   
  239.   *diag = d;
  240.  
  241.   return(buf + len + 1);
  242. }
  243.  
  244. /*----------------------------------------------------------------------*/
  245.  
  246. #define continueBit    0x80
  247. #define dataMask    0x7F
  248. #define dataBits    7
  249.  
  250. char*
  251. writeCompressedInteger(num,buf,len)
  252. unsigned long num;
  253. char* buf;
  254. long* len;
  255. /* write a binary integer in the format described on p. 40.
  256.    this might be sped up 
  257. */
  258. {
  259.   char byte;
  260.   long i;
  261.   unsigned long size;
  262.   
  263.   size = writtenCompressedIntSize(num);
  264.   CHECK_FOR_SPACE_LEFT(size,len);
  265.   
  266.   for (i = size - 1; i >= 0; i--)
  267.     { byte = num & dataMask;
  268.       if (i != (size-1))    /* turn on continue bit */
  269.     byte = (char)(byte | continueBit);
  270.       buf[i] = byte;
  271.       num = num >> dataBits;    /* don't and here */
  272.     }
  273.    
  274.   return(buf + size);
  275.  
  276. /*----------------------------------------------------------------------*/
  277.  
  278. char*
  279. readCompressedInteger(num,buf)
  280. unsigned long *num;
  281. char* buf;
  282. /* read a binary integer in the format described on p. 40.
  283.    this might be sped up 
  284. */
  285. {
  286.   register unsigned char byte;
  287.   *num = 0;
  288.   
  289.   do { 
  290.     byte = *(buf++);
  291.     *num = *num << dataBits;
  292.     *num += (byte & dataMask);
  293.   } while (byte & continueBit);
  294.   return(buf);
  295.  
  296. /*----------------------------------------------------------------------*/
  297.  
  298. #define pad    128 /* high bit is set */
  299.  
  300. char*
  301. writeCompressedIntWithPadding(num,size,buffer,len)
  302. unsigned long num;
  303. unsigned long size;
  304. char* buffer;
  305. long* len;
  306. /* Like writeCompressedInteger, except writes padding (128) to make
  307.    sure that size bytes are used.  This can be read correctly by 
  308.    readCompressedInteger()
  309. */
  310. {
  311.   char* buf = buffer;
  312.   unsigned long needed,padding;
  313.   long i;
  314.     
  315.   CHECK_FOR_SPACE_LEFT(size,len);
  316.   
  317.   needed = writtenCompressedIntSize(num);
  318.   padding = size - needed;
  319.   i = padding - 1;
  320.  
  321.   for (i = padding - 1;i >= 0;i--)
  322.     { buf[i] = pad;
  323.     }
  324.   
  325.   buf = writeCompressedInteger(num,buf + padding,len);
  326.   
  327.   return(buf);
  328.  
  329. /*----------------------------------------------------------------------*/
  330.  
  331. unsigned long
  332. writtenCompressedIntSize(num)
  333. unsigned long num;
  334. /* return the number of bytes needed to represnet the value num in
  335.    compressed format.  curently limited to 4 bytes
  336.  */
  337. {
  338.   if (num < CompressedInt1Byte) 
  339.     return(1);
  340.   else if (num < CompressedInt2Byte) 
  341.     return(2);
  342.   else if (num < CompressedInt3Byte)
  343.     return(3);
  344.   else
  345.     return(4);    
  346. }
  347.  
  348. /*----------------------------------------------------------------------*/
  349.  
  350. char*
  351. writeTag(tag,buf,len)
  352. data_tag tag;
  353. char* buf;
  354. long* len;
  355. /* write out a data tag */
  356.   return(writeCompressedInteger(tag,buf,len));
  357.  
  358. /*----------------------------------------------------------------------*/
  359.  
  360. char*
  361. readTag(tag,buf)
  362. data_tag* tag;
  363. char* buf;
  364. /* read a data tag */
  365.   return(readCompressedInteger(tag,buf));
  366.  
  367. /*----------------------------------------------------------------------*/
  368.  
  369. unsigned long 
  370. writtenTagSize(tag)
  371. data_tag tag;
  372.   return(writtenCompressedIntSize(tag));
  373. }
  374.  
  375. /*----------------------------------------------------------------------*/
  376.  
  377. data_tag
  378. peekTag(buf)
  379. char* buf;
  380. /* read a data tag without advancing the buffer */
  381. {
  382.   data_tag tag;
  383.   readTag(&tag,buf);
  384.   return(tag);
  385.  
  386. /*----------------------------------------------------------------------*/
  387.  
  388. any* 
  389. makeAny(size,data)
  390. unsigned long size;
  391. char* data;
  392. {
  393.   any* a = (any*)s_malloc((size_t)sizeof(any));
  394.   a->size = size;
  395.   a->bytes = data;
  396.   return(a);
  397. }
  398.  
  399. /*----------------------------------------------------------------------*/
  400.  
  401. void
  402. freeAny(a)
  403. any* a;
  404. /* destroy an any and its associated data. Assumes a->bytes was
  405.    allocated using the s_malloc family of libraries 
  406.  */
  407. {
  408.   if (a != NULL)
  409.     { if (a->bytes != NULL)
  410.     s_free(a->bytes);
  411.       s_free(a);
  412.     }
  413. }
  414.  
  415. /*----------------------------------------------------------------------*/
  416.  
  417. any* 
  418. duplicateAny(a)
  419. any* a;
  420. {
  421.   any* copy = NULL;
  422.  
  423.   if (a == NULL)
  424.     return(NULL);
  425.  
  426.   copy = (any*)s_malloc((size_t)sizeof(any));
  427.   copy->size = a->size;
  428.   if (a->bytes == NULL)
  429.     copy->bytes = NULL;
  430.   else
  431.     { copy->bytes = (char*)s_malloc((size_t)copy->size);
  432.       memcpy(copy->bytes,a->bytes,(size_t)copy->size);
  433.     }
  434.   return(copy);
  435. }
  436.  
  437. /*----------------------------------------------------------------------*/
  438.  
  439. char* 
  440. writeAny(a,tag,buffer,len)
  441. any* a;
  442. data_tag tag;
  443. char* buffer;
  444. long* len;
  445. /* write an any + tag and size info */
  446. {
  447.   char* buf = buffer;
  448.  
  449.   if (a == NULL)        /* handle unspecified optional args */
  450.     return(buf);
  451.   
  452.   /* write the tags */
  453.   buf = writeTag(tag,buf,len);
  454.   buf = writeCompressedInteger(a->size,buf,len);
  455.  
  456.   /* write the bytes */
  457.   CHECK_FOR_SPACE_LEFT(a->size,len);
  458.   memcpy(buf,a->bytes,(size_t)a->size);
  459.  
  460.   return(buf+a->size);
  461. }
  462.  
  463. /*----------------------------------------------------------------------*/
  464.  
  465. char* 
  466. readAny(anAny,buffer)
  467. any** anAny;
  468. char* buffer;
  469. /* read an any + tag and size info */
  470. {
  471.   char* buf = buffer;
  472.   any* a = (any*)s_malloc((size_t)sizeof(any));
  473.   data_tag tag;
  474.   
  475.   buf = readTag(&tag,buf);
  476.   buf = readCompressedInteger(&a->size,buf);
  477.   /* now simply copy the bytes */
  478.   a->bytes = (char*)s_malloc((size_t)a->size);
  479.   memcpy(a->bytes,buf,(size_t)a->size);
  480.   *anAny = a;
  481.   return(buf+a->size);
  482. }
  483.  
  484. /*----------------------------------------------------------------------*/
  485.  
  486. unsigned long 
  487. writtenAnySize(tag,a)
  488. data_tag tag;
  489. any* a;
  490. {
  491.   unsigned long size;
  492.  
  493.   if (a == NULL)
  494.     return(0);
  495.  
  496.   size = writtenTagSize(tag);
  497.   size += writtenCompressedIntSize(a->size);
  498.   size += a->size;
  499.   return(size);
  500. }
  501.  
  502. /*----------------------------------------------------------------------*/
  503.  
  504. any*
  505. stringToAny(s)
  506. char* s;
  507. {
  508.   any* a = NULL;
  509.   
  510.   if (s == NULL)
  511.     return(NULL);
  512.     
  513.   a = (any*)s_malloc((size_t)sizeof(any));
  514.   a->size = strlen(s);
  515.   a->bytes = (char*)s_malloc((size_t)a->size);
  516.   memcpy(a->bytes,s,(size_t)a->size);
  517.   return(a);
  518. }
  519.  
  520. /*----------------------------------------------------------------------*/
  521.  
  522. char*
  523. anyToString(a)
  524. any* a;
  525. {
  526.   char* s = NULL;
  527.   
  528.   if (a == NULL)
  529.     return(NULL);
  530.     
  531.   s = s_malloc((size_t)(a->size + 1));
  532.   memcpy(s,a->bytes,(size_t)a->size);
  533.   s[a->size] = '\0';
  534.   return(s);
  535. }
  536.  
  537. /*----------------------------------------------------------------------*/
  538.  
  539. char* 
  540. writeString(s,tag,buffer,len)
  541. char* s;
  542. data_tag tag;
  543. char* buffer;
  544. long* len;
  545. /* Write a C style string.  The terminating null is not written. 
  546.    This function is not part of the Z39.50 spec.  It is provided
  547.    for the convienience of those wishing to pass C strings in 
  548.    the place of an any.
  549.  */
  550. {
  551.   char* buf = buffer;
  552.   any* data = NULL;
  553.   if (s == NULL)
  554.     return(buffer);        /* handle unused optional item before making an any */
  555.   data = (any*)s_malloc((size_t)sizeof(any)); 
  556.   data->size = strlen(s);
  557.   data->bytes = s;        /* save a copy here by not using stringToAny() */
  558.   buf = writeAny(data,tag,buf,len);
  559.   s_free(data);            /* don't use freeAny() since it will free s too */
  560.   return(buf);
  561. }
  562.  
  563. /*----------------------------------------------------------------------*/
  564.  
  565. char* 
  566. readString(s ,buffer)
  567. char** s ;
  568. char* buffer;
  569. /* Read an any and convert it into a C style string.
  570.    This function is not part of the Z39.50 spec.  It is provided
  571.    for the convienience of those wishing to pass C strings in 
  572.    the place of an any. 
  573.  */
  574. {
  575.   any* data = NULL;
  576.   char* buf = readAny(&data,buffer);
  577.   *s = anyToString(data);
  578.   freeAny(data);
  579.   return(buf);
  580. }
  581.  
  582. /*----------------------------------------------------------------------*/
  583.  
  584. unsigned long 
  585. writtenStringSize(tag,s)
  586. data_tag tag;
  587. char* s;
  588. {
  589.   unsigned long size;
  590.  
  591.   if (s == NULL)
  592.    return(0);
  593.  
  594.   size = writtenTagSize(tag);
  595.   size += writtenCompressedIntSize(size);
  596.   size += strlen(s);
  597.   return(size);
  598. }
  599.  
  600. /*----------------------------------------------------------------------*/
  601.  
  602. any* 
  603. longToAny(num)
  604. long num;
  605. /* a convienience function */
  606. {
  607.   char s[40];
  608.  
  609.   sprintf(s,"%ld",num);
  610.   
  611.   return(stringToAny(s));
  612. }
  613.  
  614. /*----------------------------------------------------------------------*/
  615.  
  616. long
  617. anyToLong(a)
  618. any* a;
  619. /* a convienience function */
  620. {
  621.   long num;
  622.   char* str = NULL;
  623.   str = anyToString(a);
  624.   sscanf(str,"%ld",&num);    /* could check the result and return
  625.                    an error */
  626.   s_free(str);
  627.   return(num);
  628. }
  629.  
  630. /*----------------------------------------------------------------------*/
  631.  
  632. #define bitsPerByte    8
  633.  
  634. #ifdef ANSI_LIKE /* use ansi */
  635.  
  636. bit_map*
  637. makeBitMap(unsigned long numBits,...)
  638. /* construct and return a bitmap with numBits elements */
  639. {
  640.   va_list ap;
  641.   long i,j;
  642.   bit_map* bm = NULL;
  643.  
  644.   va_start(ap,numBits);
  645.   
  646.   bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  647.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte); 
  648.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  649.   
  650.   /* fill up the bits */
  651.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  652.     { char byte = 0;
  653.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  654.     { if ((i * bitsPerByte + j) < numBits)
  655.         { boolean bit = false;
  656.           bit = (boolean)va_arg(ap,boolean); 
  657.           if (bit)
  658.             { byte = byte | (1 << (bitsPerByte - j - 1));
  659.             }
  660.         }
  661.       }
  662.       bm->bytes[i] = byte;
  663.     }
  664.  
  665.   va_end(ap);
  666.   return(bm);
  667. }
  668.  
  669. #else /* use K & R */
  670.  
  671. bit_map*
  672. makeBitMap(va_alist)
  673. va_dcl
  674. /* construct and return a bitmap with numBits elements */
  675. {
  676.   va_list ap;
  677.   long i,j;
  678.   unsigned long numBits;
  679.   bit_map* bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  680.  
  681.   va_start(ap);
  682.   
  683.   numBits = va_arg(ap,unsigned long);
  684.  
  685.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte);
  686.   
  687.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  688.   
  689.   /* fill up the bits */
  690.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  691.     { char byte = 0;
  692.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  693.     { if ((i * bitsPerByte + j) < numBits)
  694.         { boolean bit;
  695.           bit = (boolean)va_arg(ap,int); /* really boolean, but this 
  696.                         is how it is passed on stack */
  697.           if (bit)
  698.             { byte = byte | (1 << (bitsPerByte - j - 1));
  699.             }
  700.         }
  701.       }
  702.       bm->bytes[i] = byte;
  703.     }
  704.  
  705.   va_end(ap);
  706.  
  707.   return(bm);
  708. }
  709.  
  710. #endif 
  711.  
  712. /*----------------------------------------------------------------------*/
  713.  
  714. void
  715. freeBitMap(bm)
  716. bit_map* bm;
  717. /* destroy a bit map created by makeBitMap() */
  718. {
  719.   s_free(bm->bytes);
  720.   s_free(bm);
  721. }
  722.  
  723. /*----------------------------------------------------------------------*/
  724.  
  725. /* use this routine to interpret a bit map.  pos specifies the bit 
  726.    number.  bit 0 is the Leftmost bit of the first byte.  
  727.    Could do bounds checking.
  728.  */
  729.  
  730. boolean
  731. bitAtPos(pos,bm)
  732. long pos;
  733. bit_map* bm;
  734. {
  735.   if (pos > bm->size*bitsPerByte)
  736.     return false;
  737.   else
  738.     return((bm->bytes[(pos / bitsPerByte)] & 
  739.         (0x80>>(pos % bitsPerByte))) ?
  740.        true : false);
  741. }
  742.  
  743. /*----------------------------------------------------------------------*/
  744.  
  745. char*
  746. writeBitMap(bm,tag,buffer,len)
  747. bit_map* bm;
  748. data_tag tag;
  749. char* buffer;
  750. long* len;
  751. /* write a bitmap + type and size info */
  752.   return(writeAny((any*)bm,tag,buffer,len));
  753. }
  754.  
  755. /*----------------------------------------------------------------------*/
  756.  
  757. char*
  758. readBitMap(bm,buffer)
  759. bit_map** bm;
  760. char* buffer;
  761. /* read a bitmap + type and size info */
  762.   return(readAny((any**)bm,buffer));
  763. }
  764.  
  765. /*----------------------------------------------------------------------*/
  766.  
  767. char* 
  768. writeByte(byte,buf,len)
  769. unsigned long byte;
  770. char* buf;
  771. long* len;
  772. {
  773.   CHECK_FOR_SPACE_LEFT(1L,len);
  774.   buf[0] = byte & 0xFF; /* we really only want the first byte */
  775.   return(buf + 1);
  776. }
  777.  
  778. /*----------------------------------------------------------------------*/
  779.  
  780. char* 
  781. readByte(byte,buf)
  782. unsigned char* byte;
  783. char* buf;
  784. {
  785.   *byte = buf[0];
  786.   return(buf + 1);
  787. }
  788.  
  789. /*----------------------------------------------------------------------*/
  790.  
  791. char* 
  792. writeBoolean(flag,buf,len)
  793. boolean flag;
  794. char* buf;
  795. long* len;
  796. {
  797.   return(writeByte(flag,buf,len));
  798. }
  799.  
  800. /*----------------------------------------------------------------------*/
  801.  
  802. char* 
  803. readBoolean(flag,buffer)
  804. boolean* flag;
  805. char* buffer;
  806. {
  807.   unsigned char byte;
  808.   char* buf = readByte(&byte,buffer);
  809.   *flag = (byte == true) ? true : false;
  810.   return(buf);
  811. }
  812.  
  813. /*----------------------------------------------------------------------*/
  814.  
  815. char*
  816. writePDUType(pduType,buf,len)
  817. pdu_type pduType;
  818. char* buf;
  819. long* len;
  820. /* PDUType is a single byte */
  821. {
  822.   return(writeBinaryInteger((long)pduType,(unsigned long)1,buf,len));
  823.  
  824. /*----------------------------------------------------------------------*/
  825.  
  826. char*
  827. readPDUType(pduType,buf)
  828. pdu_type* pduType;
  829. char* buf;
  830. /* PDUType is a single byte */
  831. {
  832.   return(readBinaryInteger((long*)pduType,(unsigned long)1,buf));
  833.  
  834. /*----------------------------------------------------------------------*/
  835.  
  836. pdu_type
  837. peekPDUType(buf)
  838. char* buf;
  839. /* read the next pdu without advancing the buffer, Note that this 
  840.    function is to be used on a buffer that is known to contain an
  841.    APDU.  The pdu_type is written HEADER_LEN bytes into the buffer
  842.  */
  843. {
  844.   pdu_type pdu;
  845.   readPDUType(&pdu,buf + HEADER_LEN);
  846.   return(pdu);
  847. }
  848.  
  849. /*----------------------------------------------------------------------*/
  850.  
  851. #define BINARY_INTEGER_BYTES    sizeof(long) /* the number of bytes used by
  852.                         a "binary integer" */
  853. char*
  854. writeBinaryInteger(num,size,buf,len)
  855. long num;
  856. unsigned long size;
  857. char* buf;
  858. long* len;
  859. /* write out first size bytes of num - no type info
  860.   XXX should this take unsigned longs instead ???  */
  861. {
  862.   long i;
  863.   char byte;
  864.  
  865.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  866.     return(NULL);        /* error */
  867.  
  868.   CHECK_FOR_SPACE_LEFT(size,len);
  869.  
  870.   for (i = size - 1; i >= 0; i--)
  871.     { byte = (char)(num & 255);
  872.       buf[i] = byte;
  873.       num = num >> bitsPerByte; /* don't and here */
  874.     }
  875.  
  876.   return(buf + size);
  877. }
  878.  
  879. /*----------------------------------------------------------------------*/
  880.  
  881. char*
  882. readBinaryInteger(num,size,buf)
  883. long* num;
  884. unsigned long size;
  885. char* buf;
  886. /* read in first size bytes of num - no type info
  887.   XXX this should take unsigned longs instead !!! */
  888. {
  889.   long i;
  890.   unsigned char byte;
  891.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  892.     return(buf);        /* error */
  893.   *num = 0;
  894.   for (i = 0; i < size; i++)
  895.     { byte = buf[i];
  896.       *num = *num << bitsPerByte;
  897.       *num += byte;
  898.     }
  899.   return(buf + size);
  900. }
  901.  
  902. /*----------------------------------------------------------------------*/
  903.  
  904. unsigned long 
  905. writtenCompressedBinIntSize(num)
  906. long num;
  907. /* return the number of bytes needed to represent the value num.
  908.    currently limited to max of 4 bytes 
  909.    Only compresses for positive nums - negatives get whole 4 bytes
  910.  */
  911. {
  912.   if (num < 0L)
  913.     return(4);
  914.   else if (num < 256L)        /* 2**8 */
  915.     return(1);
  916.   else if (num < 65536L)    /* 2**16 */
  917.     return(2);
  918.   else if (num < 16777216L)    /* 2**24 */
  919.     return(3);
  920.   else
  921.     return(4);
  922. }
  923.  
  924. /*----------------------------------------------------------------------*/
  925.  
  926. char*
  927. writeNum(num,tag,buffer,len)
  928. long num;
  929. data_tag tag;
  930. char* buffer;
  931. long* len;
  932. /* write a binary integer + size and tag info */
  933. {
  934.   char* buf = buffer;
  935.   long size = writtenCompressedBinIntSize(num);
  936.   
  937.   if (num == UNUSED)
  938.     return(buffer);
  939.     
  940.   buf = writeTag(tag,buf,len);
  941.   buf = writeCompressedInteger(size,buf,len); 
  942.   buf = writeBinaryInteger(num,(unsigned long)size,buf,len); 
  943.   return(buf);
  944. }
  945.  
  946. /*----------------------------------------------------------------------*/
  947.  
  948. char*
  949. readNum(num,buffer)
  950. long* num;
  951. char* buffer;
  952. /* read a binary integer + size and tag info */
  953. {
  954.   char* buf = buffer;
  955.   data_tag tag;
  956.   unsigned long size;
  957.   unsigned long val;
  958.   
  959.   buf = readTag(&tag,buf);
  960.   buf = readCompressedInteger(&val,buf);
  961.   size = (unsigned long)val;
  962.   buf = readBinaryInteger(num,size,buf);
  963.   return(buf);
  964. }
  965.  
  966. /*----------------------------------------------------------------------*/
  967.  
  968. unsigned long 
  969. writtenNumSize(tag,num)
  970. data_tag tag;
  971. long num;
  972. {
  973.   long dataSize = writtenCompressedBinIntSize(num);
  974.   long size;
  975.   
  976.   size = writtenTagSize(tag); /* space for the tag */
  977.   size += writtenCompressedIntSize(dataSize); /* space for the size */
  978.   size += dataSize; /* space for the data */
  979.   
  980.   return(size);
  981. }
  982.  
  983. /*----------------------------------------------------------------------*/
  984.  
  985. typedef void (voidfunc)();
  986.  
  987. void
  988. doList(list,func)
  989. void** list;
  990. voidfunc *func;
  991. /* call func on each element of the NULL terminated list of pointers */
  992. {
  993.   register long i;
  994.   register void* ptr = NULL;
  995.   if (list == NULL)
  996.     return;
  997.   for (i = 0,ptr = list[i]; ptr != NULL; ptr = list[++i])
  998.     (*func)(ptr);
  999. }
  1000.  
  1001. /*----------------------------------------------------------------------*/
  1002.  
  1003. char* 
  1004. writeProtocolVersion(buf,len)
  1005. char* buf;
  1006. long* len;
  1007. /* write a bitmap describing the protocols available */
  1008. {
  1009.   static bit_map* version = NULL;
  1010.  
  1011.   if (version == NULL)
  1012.    { version = makeBitMap((unsigned long)1,true); /* version 1! */
  1013.    }
  1014.     
  1015.   return(writeBitMap(version,DT_ProtocolVersion,buf,len));
  1016. }
  1017.  
  1018. /*----------------------------------------------------------------------*/
  1019.  
  1020. char*
  1021. defaultImplementationID()
  1022. {
  1023.   static char    ImplementationID[] = "TMC";
  1024.   return(ImplementationID);
  1025. }
  1026.  
  1027. /*----------------------------------------------------------------------*/
  1028.  
  1029. char*
  1030. defaultImplementationName()
  1031. {
  1032.   static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
  1033.   return(ImplementationName);
  1034. }
  1035.  
  1036. /*----------------------------------------------------------------------*/
  1037.  
  1038. char*
  1039. defaultImplementationVersion()
  1040. {
  1041.   static char    ImplementationVersion[] = "2.0A";
  1042.   return(ImplementationVersion);
  1043. }
  1044.  
  1045. /*----------------------------------------------------------------------*/
  1046.  
  1047.